package com.zhku.yygh.cmn.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhku.yygh.cmn.listener.DictListener;
import com.zhku.yygh.cmn.mapper.DictMapper;
import com.zhku.yygh.cmn.service.DictService;
import com.zhku.yygh.model.cmn.Dict;
import com.zhku.yygh.vo.cmn.DictEeVo;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

/**
 * @BelongsProject: yygh-parent
 * @BelongsPackage: com.zhku.yygh.cmn.service.impl
 * @Author: "deweyMDH"
 * @CreateTime: 2023-05-11  16:49
 * @Version: 1.0
 */
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {

    /**
     * 根据上级id获取子节点数据列表
     * @param id
     * 这里做了缓存处理，把查到的数据加入到， dict命名空间下，方便
     */
    @Override
    @Cacheable(value = "dict",keyGenerator = "keyGenerator")
    public List<Dict> findChlidData(Long id) {
        QueryWrapper<Dict> wrapper = new QueryWrapper();
        wrapper.eq("parent_id", id);
        List<Dict> dictList = baseMapper.selectList(wrapper);
        for (Dict dict: dictList) {
            Long dictId = dict.getId();
            boolean children = this.isChildren(dictId);
            dict.setHasChildren(children);
        }
        return dictList;
    }

    //判断id下面是否有子节点
    private boolean isChildren(Long id) {
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id",id);
        // 这个方法，可以快速查，数据库中， parent_id = id 条件下，是否有数据，不需要查出数据，只需要判断
        Integer count = baseMapper.selectCount(wrapper);
        // 0>0    1>0
        return count>0;
    }

    // 导出前端保存的数据字典到excel文件中
    @Override
    public void exportData(HttpServletResponse response) {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 设置导出的文件名
        String fileName = "dict";
        response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");

        // 查询数据库数据
        List<Dict> dictList = baseMapper.selectList(null);
        List<DictEeVo> dictVoList = new LinkedList<>();
        for (Dict dict: dictList) {
            // dict --> dictEevo , 因为dict有些字段是不需要在前段展示的，比如 create_time等
            DictEeVo dictEeVo = new DictEeVo();
            BeanUtils.copyProperties(dict, dictEeVo);
            dictVoList.add(dictEeVo);
        }

        try {
            EasyExcel.write(response.getOutputStream(), DictEeVo.class)
                    .sheet("dict").doWrite(dictVoList);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 导入excel文件中的数据到数据库中
     * allEntries = true: 方法调用后清空所有缓存
     * @param file
     */
    @Override
    @CacheEvict(value = "dict", allEntries=true)
    public void importData(MultipartFile file) {
        try {
            // 这里因为 baseMapper 是一个泛型类的实例，只要是 BaseMapper 的子类即可，根据多态，是可以赋值给 DictMapper的
            EasyExcel.read(file.getInputStream(), DictEeVo.class, new DictListener(baseMapper))
                    .sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

//    ------------- 这里是别的服务调用的方法
    @Override
    public String getDictName(String dictCode, String value) {
        //如果value能唯一定位数据字典，parentDictCode可以传空，例如：省市区的value值能够唯一确定
        if (StringUtils.isEmpty(dictCode)){
            QueryWrapper<Dict> wrapper = new QueryWrapper<>();
            wrapper.eq("value", value);
            Dict dict = baseMapper.selectOne(wrapper);
            return dict.getName();
        } else {
            // 先根据dictCode 查到id ，再找这个id下的子节点
            Dict codeDict = this.getDictByDictcode(dictCode);
            Long id = codeDict.getId();

            Dict finaldict = baseMapper.selectOne(new QueryWrapper<Dict>()
                    .eq("parent_id", codeDict.getId())
                    .eq("value", value));

            return finaldict.getName();
        }
    }

    private Dict getDictByDictcode(String dictCode){
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("dict_code", dictCode);
        Dict one = baseMapper.selectOne(wrapper);
        return one;
    }

    // 根据dictCode获取下级节点
    @Override
    public List<Dict> findByDictCode(String dictCode) {
        // 根据dictCode查询id
        Dict dict = this.getDictByDictcode(dictCode);
        // 根据查出来的父节点，查子节点
        List<Dict> dictList = this.findChlidData(dict.getId());
        return dictList;
    }
}
